home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1997 October / pcx14_9710.iso / swag / math.swg / 0114_Euler's Indice to Prime Numbers.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-08-30  |  5.4 KB  |  183 lines

  1. (*
  2.                 Daniel Doubrovkine - dblock@infomaniak.ch
  3.    part of the Expression Calculator 2.0 Multithread, destribute freely
  4.               http://www.infomaniak.ch/~dblock/express.htm
  5.     (ref. Haussman, Simple Algebra course at the University of Geneva)
  6.  
  7.                             "Euler's Indice"
  8.        euler's indice is a insomorphe function phi: Zm->Z1*Z2...Zn
  9.     means the decomposition of a number into a primes product is unique
  10.     with phi(n):=n*(1-1/p1)*...*(1-1/pn) where pi are primes taken once
  11.     from the decomposition.
  12.     ex: (following algorith steps):
  13.        168=2*84
  14.        168=2*2*42
  15.        168=2*2*2*21
  16.        168=2*2*2*3*7 where all are primes!
  17.   now, phi(168)=168*(1-1/2)(1-1/3)(1-1/7)=48 (this is always an integer!)
  18.        thus, 168 has 48 primes to it.
  19. *)
  20.  
  21. (*defining a dynamic primes array, so this function will never be limited*)
  22. type
  23.    PPrimesArray=^TPrimesArray;
  24.    TPrimesArray=record
  25.       Prime:longint;
  26.       NextPrime:PPrimesArray;
  27.       end;
  28.  
  29.  
  30.    (*adding a prime to the array*)
  31.    procedure PrimesAdd(var AllPrimes: PPrimesArray;Prime:longint);
  32.    var
  33.       TempPrimes:PPrimesArray;
  34.    begin
  35.       TempPrimes:=AllPrimes;
  36.       while (TempPrimes<>nil) do begin
  37.          if TempPrimes^.Prime=Prime then exit;
  38.          TempPrimes:=TempPrimes^.NextPrime;
  39.          end;
  40.       new(TempPrimes);
  41.       TempPrimes^.Prime:=Prime;
  42.       TempPrimes^.NextPrime:=AllPrimes;
  43.       AllPrimes:=TempPrimes;
  44.       end;
  45.  
  46.    (*removing the primes array*)
  47.    procedure PrimesRemove(AllPrimes: PPrimesArray);
  48.    var
  49.       TempPrimes:PPrimesArray;
  50.    begin
  51.       while AllPrimes<>nil do begin
  52.          TempPrimes:=AllPrimes;
  53.          AllPrimes:=AllPrimes^.NextPrime;
  54.          Dispose(TempPrimes);
  55.          end;
  56.       end;
  57.  
  58.    (*by the way, this routine uses some code from swag*)
  59.    function GeneratePrimes(var AllPrimes: PPrimesArray;n: longint):longint;
  60.     procedure CalculateTPrime(n: longint);
  61.     var
  62.       TempPrime: PPrimesArray;
  63.       CurrentPrime: LongInt;
  64.       prime:boolean;
  65.       number,max_div,divisor,lastprime:longint;
  66.     begin
  67.       CurrentPrime:=AllPrimes^.Prime;
  68.       for number:=CurrentPrime to MaxLongInt do begin
  69.          max_div:=Round(Sqrt(number)+0.5);
  70.          prime:=number mod 2 <> 0;
  71.          divisor:=3;
  72.          while prime and (divisor<max_div) do begin
  73.                prime:=number mod divisor <>0;
  74.                divisor:=divisor+2;
  75.                end;
  76.          if prime then begin
  77.          if AllPrimes^.Prime<CurrentPrime then PrimesAdd(AllPrimes,CurrentPrime);
  78.             CurrentPrime:=number;
  79.          if n<CurrentPrime then exit;
  80.          end;
  81.          end;
  82.          end;
  83.  
  84.    var
  85.       TempPrime: PPrimesArray;
  86.       CurrentPrime: LongInt;
  87.       prime:boolean;
  88.       number,max_div,divisor,lastprime:longint;
  89.    begin
  90.      PrimesAdd(AllPrimes,1);
  91.      PrimesAdd(AllPrimes,2);
  92.       if (n>-1) and (n<1) then begin
  93.          writeln('Prime requires values |x|>1');
  94.          halt;
  95.          end;
  96.       if n>maxlongint then begin
  97.          writeln('prime limit too large');
  98.          halt;
  99.          end;
  100.  
  101.       n:=abs(n);
  102.  
  103.       if (n<=AllPrimes^.Prime) then begin
  104.       TempPrime:=AllPrimes;
  105.          while TempPrime<>nil do begin
  106.                CurrentPrime:=TempPrime^.Prime;
  107.                if n>=TempPrime^.Prime then begin
  108.                   GeneratePrimes:=TempPrime^.Prime;
  109.                   exit;
  110.                   end;
  111.            TempPrime:=TempPrime^.NextPrime;
  112.            end;
  113.            end;
  114.       CalculateTPrime(n);
  115.       GeneratePrimes:=AllPrimes^.Prime;
  116.       end;
  117.  
  118.  
  119. function phi(var AllPrimes:PPrimesArray;Value:longint):longint;
  120. var
  121.    UsedPrimes:PPrimesArray;
  122.    (*this is partailly from swag...*)
  123.    procedure Factoring(lin:longint);
  124.    var
  125.       lcnt:longint;
  126.    begin
  127.       lcnt:=2;
  128.       if GeneratePrimes(AllPrimes,lin)=lin then begin
  129.          write(' ',lin);
  130.          PrimesAdd(UsedPrimes,lin);
  131.          end else
  132.          while(lcnt*lcnt<=lin) do begin
  133.             if (lin mod lcnt) = 0 then begin
  134.                if GeneratePrimes(AllPrimes,lcnt)<>lcnt then factoring(lcnt)
  135.                   else begin
  136.                      write(' ',lcnt);
  137.                      primesadd(UsedPrimes,lcnt);
  138.                      end;
  139.                if GeneratePrimes(AllPrimes,lin div lcnt)<>(lin div lcnt) then factoring(lin div lcnt)
  140.                   else begin
  141.                      write(' ',lin div lcnt);
  142.                      primesadd(UsedPrimes,lin div lcnt);
  143.                      end;
  144.                exit;
  145.                end;
  146.          lcnt:=lcnt+1;
  147.          end;
  148.       end;
  149.  
  150.    var
  151.       FinalResult:real;
  152.       TempPrimes:PPrimesArray;
  153.    begin
  154.      if Value=0 then begin
  155.         Phi:=0;
  156.         exit;
  157.         end;
  158.      Value:=Abs(Value);
  159.      FinalResult:=Value;
  160.      UsedPrimes:=nil;
  161.      write('Decomposition of ',Value:0,':');
  162.      Factoring(Value);
  163.      writeln;
  164.      TempPrimes:=UsedPrimes;
  165.      while TempPrimes<>nil do begin
  166.         FinalResult:=FinalResult*(1-1/TempPrimes^.Prime);
  167.         TempPrimes:=TempPrimes^.NextPrime;
  168.         end;
  169.      phi:=trunc(FinalResult);
  170.      PrimesRemove(UsedPrimes);
  171.      writeln('Euler''s indice for ',Value:0,' is ',trunc(FinalResult));
  172.      writeln('(there are ',trunc(FinalResult),' primes to ',Value,')');
  173.    end;
  174.  
  175. var
  176.    AllPrimes: PPrimesArray;
  177. begin
  178.      Phi(AllPrimes,168);
  179.      PrimesRemove(AllPrimes);
  180.    end.
  181.  
  182.  
  183.